/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.njzxw.fs.commonutil.util;

import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 *
 * 锁定单个对象
 *
 * @author eliayng
 */
@Component
public class LockObject {

    /**
     * 保证原子操作
     */
    private static ConcurrentMap<Object, Lock> lockMap = new ConcurrentHashMap<Object, Lock>();

    public org.slf4j.Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 默认等待锁15秒
     *
     * @param lockObj
     * @return
     */
    public boolean try15Lock(Object lockObj) {
        return tryLock(lockObj, 15, TimeUnit.SECONDS);
    }

    /**
     * 获取锁,锁定单个对象
     *
     * @param lockObj
     * @return
     */
    public boolean tryLock(Object lockObj, long time, TimeUnit unit) {
        Lock writeLock = new ReentrantReadWriteLock().writeLock();
        //进行一次存放，如果存在不替换，返回旧的字符串
        Lock signal = lockMap.putIfAbsent(lockObj, writeLock);
        //只有第一个执行成功的返回是null
        if (signal == null) {
            signal = lockMap.get(lockObj);
        }

        try {
            if (signal.tryLock(15, TimeUnit.SECONDS)) {
                return true;
            }
        } catch (Exception ex) {
            logger.error("获取时间等待锁失败", ex);
        }
        return false;
    }

    /**
     * 释放锁
     *
     * @return
     */
    public boolean unlock(Object lockObj, Lock lock) {
        Lock signal = null;
        if (lockMap.containsKey(lockObj)) {
            signal = lockMap.get(lockObj);
        }
        if(signal == null){
            signal = lock;
        }

        if (signal != null) {
            signal.unlock();
        }

        return false;
    }

    /**
     * 单纯移除锁
     *
     * @return
     */
    public boolean removeLock(Object lockObj, Lock lock) {
        return lockMap.remove(lockObj, lock);
    }

    /**
     * 释放并移除锁
     *
     * @return
     */
    public boolean removeUnLock(Object lockObj, Lock lock) {
        if (unlock(lockObj, lock)) {
            return removeLock(lockObj, lock);
        }
        return false;
    }

    /**
     * 释放锁
     *
     * @return
     */
    public boolean unlock(Object lockObj) {
        Lock signal = null;
        if (lockMap.containsKey(lockObj)) {
            signal = lockMap.get(lockObj);
        }

        if (signal != null) {
            signal.unlock();
        }

        return false;
    }

    /**
     * 单纯移除锁
     *
     * @return
     */
    public boolean removeLock(Object lockObj) {
        Lock lock = lockMap.remove(lockObj);
        if (lock != null) {
            lock.unlock();
        }
        return true;
    }

    /**
     * 释放并移除锁
     *
     * @return
     */
    public boolean removeUnLock(Object lockObj) {
        if (unlock(lockObj)) {
            return removeLock(lockObj);
        }
        return false;
    }

}
